package org.chipu.jnids.beans;

import java.io.*;
import java.lang.ref.SoftReference;
import java.util.List;
import java.util.Map;
import org.chipu.jnids.sancp.NetFlowReader;
import org.chipu.shared.util.file.BidirectionalReader;

// IMPROVE the caching of flows, thus maintain a hard reference in the last StatFileHelper
public final class StatFileHelper {
	public final File file;
	/** Start time of the flow that starts first (not the first one) */
	public final int startTimeInSeconds;
	/** Stop time of the last flow (it is the last one) */
	public final int stopTimeInSeconds;
	/**
	 * Number of the first lines to be read before deciding about the starting time of the first flow in the file
	 */
	private final static int numberOfFirstLines = 20;
	private SoftReference<List<Flow>> ref;

	public StatFileHelper(File file) throws IllegalArgumentException, IOException {
		if (!file.exists() || !file.canRead())
			throw new IllegalArgumentException("Wrong file. exists?" + file.exists() + ". canread?" + file.canRead());
		this.file = file;
		stopTimeInSeconds = getLastStoppedFlowTime();
		startTimeInSeconds = getFirstStartedFlowTime();
	}

	/** If the file does not have any result in the last 2 lines, then it returns 0 */
	private int getLastStoppedFlowTime() throws IllegalArgumentException, IOException {
		// the last line may be empty
		List<String> l = BidirectionalReader.tail(file, 3);
		String toUse = null;
		for(int i = l.size() - 1; i >= 0; i--)
			if (!"".equals(l.get(i))) {
				toUse = l.get(i);
				break;
			}
		if (toUse == null)
			return 0;
		Map<String, Number> data = NetFlowReader.getInstance().getLineData(toUse, "stats");
		// SnapShotCreator.convertToFlow(data).stopTimeInSeconds;
		Number n = data.get("stop_time_gmt");
		if (n == null)
			return data.get("start_time_gmt").intValue() + data.get("duration").intValue();
		return n.intValue();
	}

	private int getFirstStartedFlowTime() throws IOException {
		// SEE using BidirectionalReader.head(file, n);?
		BufferedReader d = null;
		try {
			d = new BufferedReader(new FileReader(file));
			String tmp = "";
			int i = numberOfFirstLines;
			int startTime = Integer.MAX_VALUE;
			while(tmp != null && i > 0) {
				if (tmp != "")
					startTime = Math.min(NetFlowReader.getInstance().getLineData(tmp, "stats").get("start_time_gmt").intValue(),
						startTime);
				tmp = d.readLine();
				i--;
			}
			return startTime;
		} finally {
			if (d != null)
				d.close();
		}
	}

	/** They are sorted by stop time (the same as the log files) */
	public List<Flow> getFlows() throws Exception {
		if (ref != null && ref.get() == null)
			ref = null;
		if (ref == null)
			ref = new SoftReference<List<Flow>>(NetFlowReader.getInstance().retrieveFlows(file, "stats"));
		return ref.get();
	}
}